package mobilesmil.services;

import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.InputStreamReader;
import java.net.InetAddress;
import java.net.URL;
import java.net.URLConnection;
import java.util.ArrayList;
import java.util.zip.ZipEntry;
import java.util.zip.ZipInputStream;

import mobilesmil.activity.HomeActivity;

import org.apache.commons.net.ftp.FTPClient;

import android.os.Environment;
import android.util.Log;
/**
 * This class will ping the database every 5 seconds looking for messages
 * It will download unzip and clean up any messages on the server
 */
public class MessageReceiver implements Runnable 
{
	private String mToNumber;
	private ArrayList<String> mDeleteIDs;
	private ArrayList<String> mMessages;
	private ArrayList<String> mFromNumbers;
	private HomeActivity mHomeActivity;
	private static final int BUFFER = 16384;
	private static final int WAIT_TIME = 5000;
	
	/**
	 * This initializes the number for the receiver.  Also the home activity for accessing the UI thread.
	 * @param toNumber
	 * @param homeActivity
	 */
	public MessageReceiver(String toNumber, HomeActivity homeActivity)
	{
		mToNumber = toNumber;
		mDeleteIDs = new ArrayList<String>();
		mFromNumbers = new ArrayList<String>();
		mMessages = new ArrayList<String>();
		mHomeActivity = homeActivity;
	}

	@Override
	public void run()
	{
		try
		{
			while(true)
			{
				mDeleteIDs.clear();
				mMessages.clear();
				mFromNumbers.clear();
				Log.i("Receiver Thread - run()", "Start Running");
				if(getMessages())
				{
					Log.i("Receiver Thread - run()", "Found new messages");
					if(downloadMessages())
					{
						Log.i("Receiver Thread - run()", "Downloaded a new message");
						if(unzipMessages()) {
                            deleteMessages();
                            for(int i = 0; i < mMessages.size(); i++) {
                                mHomeActivity.showNotification(mFromNumbers.get(i),mMessages.get(0).substring(0, mMessages.get(0).lastIndexOf('_')));
                            }
                        }
					}
				}
				synchronized(this) {
					Log.i("Receiver Thread - run()", "Waiting");
					wait(WAIT_TIME);
				}
			}
		}
		catch(InterruptedException iExc)
		{
			Log.e("RunInterrupted", iExc.toString());
		}
		
	}
	
	/**
	 * This method will query the server for new messages that are intended for this phone.
	 * @return
	 */
	private boolean getMessages()
	{
		String url = SmilMessages.SERVER_PHP_ABSOLUTE_DIR + "receive.php?";
		url += "to_number=" 	+ "" + mToNumber 	+ "";
		
		try
		{
			Log.i("Receiver Thread - getMessages()", "Attempt to get messages for phone # " + mToNumber);
			URL sendURL = new URL(url);
			URLConnection sendScript = sendURL.openConnection();
			BufferedReader in = new BufferedReader(new InputStreamReader(sendScript.getInputStream()));
			String responseLine = "";

			if(in != null)
			{
				int count = 0;
				while((responseLine = in.readLine())!=null)
				{
					switch(count % 3)
					{
						case 0:
							mDeleteIDs.add(responseLine.trim());
							break;
						case 1:
							mMessages.add(responseLine.trim());
							break;
						case 2:
							mFromNumbers.add(responseLine.trim());
							break;
					}
					count += 1;
				}
				in.close();
			}
			if(mMessages.size() > 0) {
				Log.i("Receiver Thread - getMessages()", "Got " + mMessages.size() + " new message(s)");
				return true;
			}
			else {
				Log.i("Receiver Thread - getMessages()", "No new messages to get");
				return false;
			}
		}
		catch(Exception exc)
		{
			Log.e("Receiver Thread - getMessages()", exc.toString());
			exc.printStackTrace();
			return false;
		}
	}
	
	/**
	 * This will download all the messages that are available
	 * @return
	 */
	private boolean downloadMessages()
	{
		try
		{
			FTPClient ftpClient = null;
			FileOutputStream fileOut = null;
			Log.i("Receiver Thread - downloadMessages()", "Attempt to download messages (size " + mMessages.size() + ")");
			try {
				ftpClient = new FTPClient();
				ftpClient.connect(InetAddress.getByName(SmilMessages.SERVER_HOST));
				ftpClient.login(SmilMessages.SERVER_USERNAME, SmilMessages.SERVER_PASSWORD);
				ftpClient.changeWorkingDirectory(SmilMessages.SERVER_SMIL_DIR);
				ftpClient.setFileType(FTPClient.BINARY_FILE_TYPE);
				ftpClient.enterLocalPassiveMode();
				ftpClient.setBufferSize(BUFFER);
				for(int index = 0; index < mMessages.size(); index++)
				{
					Log.i("Receiver Thread - downloadMessages()", "Begin downloading message " + index);
					fileOut = new FileOutputStream(new File(Environment.getExternalStorageDirectory() + "/" + mMessages.get(index)));
					ftpClient.retrieveFile(mMessages.get(index), fileOut);
					Log.i("Receiver Thread - downloadMessages()", "Finished downloading message " + mMessages.get(index));
				}
			} catch (Exception e) { throw e; }
			finally {
				if(fileOut != null) {
					fileOut.flush();
					fileOut.close();
				}
				if(ftpClient != null) {
					ftpClient.logout();
					ftpClient.disconnect();
				}
			}
			return true;
		} catch(Exception e) {
			Log.e("Receiver Thread - downloadMessages()", e.toString());
			e.printStackTrace();
			return false;
		}
	}
	
	
	/**
	 * Unzips messages that are received
	 * @return
	 */
	private boolean unzipMessages()
	{
		try
		{
			Log.i("Receiver Thread - unzipMessages()", "Attempt to unzip messages");
			for(int index = 0; index < mMessages.size(); index++)
			{
				BufferedOutputStream dest = null;
		        FileInputStream fis = new FileInputStream(Environment.getExternalStorageDirectory() + "/" + mMessages.get(index));
		        ZipInputStream zis = new ZipInputStream(new BufferedInputStream(fis));
		        
		        ZipEntry entry;
		        while((entry = zis.getNextEntry()) != null)
		        {
		        	Log.i("Receiver Thread - unzipMessages()", "Begin unzipping file " + mMessages.get(index));
		        	if(entry.getName().toString().endsWith(".smil"))
		        		SmilMessages.setReceivedAndUnPlayed(mHomeActivity, entry.getName().toString());
		        	int count;
		            byte data[] = new byte[BUFFER];
		            // write the files to the disk
		            FileOutputStream fos = new FileOutputStream(Environment.getExternalStorageDirectory() + "/" + entry.getName());
		            dest = new BufferedOutputStream(fos, BUFFER);
		            while ((count = zis.read(data, 0, BUFFER)) != -1)
		            {
		               dest.write(data, 0, count);
		            }
		            dest.flush();
		            dest.close();
		            Log.i("Receiver Thread - unzipMessages()", "Finished unzipping file " + mMessages.get(index));
		        }
		         zis.close();

			}
		}
		catch(Exception exc)
		{
			Log.e("Receiver Thread - unzipFiles()", exc.toString());
			exc.printStackTrace();
			return false;
		}
		return true;
	}
	
	/**
	 * deletes the zip files on the local hard drive and also the
	 */
	private void deleteMessages()
	{
		String url;
		try
		{
			for(int index = 0; index < mMessages.size(); index++)
			{
				url = SmilMessages.SERVER_PHP_ABSOLUTE_DIR + "delete.php?";
				url += "id=" + "\"" + mDeleteIDs.get(index) + "\"";
				
				URL sendURL = new URL(url);
				URLConnection sendScript = sendURL.openConnection();
				BufferedReader in = new BufferedReader(new InputStreamReader(sendScript.getInputStream()));
				String responseLine = "";
				
				StringBuffer fullResponse = new StringBuffer();
				while((responseLine = in.readLine())!=null)
				{
					fullResponse.append(responseLine);
				}
				
				FTPClient ftpClient = new FTPClient();
				ftpClient.connect(InetAddress.getByName(SmilMessages.SERVER_HOST));
				ftpClient.login(SmilMessages.SERVER_USERNAME, SmilMessages.SERVER_PASSWORD);
				ftpClient.changeWorkingDirectory(SmilMessages.SERVER_SMIL_DIR);
				ftpClient.deleteFile(mMessages.get(index));
				ftpClient.enterLocalPassiveMode();
				ftpClient.logout();
				ftpClient.disconnect();
				
				File message = new File(Environment.getExternalStorageDirectory() +"/" + mMessages.get(index));
				if(message.exists())
					message.delete();
			}
		}
		catch(Exception exc)
		{
			Log.e("DeletingFile", exc.toString());
		}
		
	}

}
